// js 按顺序执行代码的，但是当 setTimeout 这种操作时，会在另一个线程中执行，所以代码会先执行完，再执行 setTimeout 中的代码
{
  function getData() {
    // 延迟 1s 返回数据
    setTimeout(() => {
      const data = [1, 2, 3];
      console.log(data);
    }, 1e3);
  }

  function hello() {
    console.log("hello, world!");
  }

  // getData();
  // hello();
}

// 当执行耗时操作时，就需要回调函数在耗时操作后续做一些逻辑处理
{
  function getData(callback) {
    // 延迟 1s 返回数据
    setTimeout(() => {
      const data = [1, 2, 3];
      callback(data);
    }, 1e3);
  }

  function hello() {
    console.log("hello, world!");
  }

  getData((data) => {
    console.log("数据", data);
    hello();
  });
  hello();
}

// 回调函数容易造成回调地狱（嵌套）
{
  function login(username, password, callback) {
    setTimeout(() => {
      callback({
        id: "fdjskhfhhj49082193sdhj",
      });
    }, 30);
  }

  function getUserInfoWithId(id, callback) {
    setTimeout(() => {
      callback({
        username: "张三",
        age: 18,
        gender: "male",
        address: "中国",
        role: "normal",
      });
    }, 30);
  }

  function getRolePermission(role, callback) {
    setTimeout(() => {
      callback({
        modules: ["chat"],
      });
    }, 30);
  }

  login("张三", "123456", (id) => {
    console.log("用户编号: ", id);
    getUserInfoWithId(id, (info) => {
      console.log("用户信息: ", info);
      getRolePermission(info.role, (permission) => {
        console.log("用户角色权限：", permission);
        console.log(permission);
      });
    });
  });
}

// Promise：有三种状态。pending（等待中）、fulfilled（已完成）、rejected（已拒绝）
// Promise 是一个类，实例化时需要传入一个函数，这个函数有两个参数 resolve 和 reject，分别是成功和失败的回调函数
{
  const promise = new Promise((resolve, reject) => {
    setTimeout(() => {
      try {
        const data = { name: "张三" };
        const response = JSON.parse(JSON.stringify(data));
        resolve(response);
      } catch (error) {
        reject(error);
      }
    }, 1e3);
  });
  promise
    .then((data) => {
      console.log("数据", data);
    })
    .catch((error) => {
      console.error("错误", error);
    });
}

// async / await 可以让 Promise 的代码看起来像同步代码，更加简洁
{
  const promise = await new Promise((resolve, reject) => {
    setTimeout(() => {
      try {
        const data = { name: "张三" };
        const response = JSON.parse(JSON.stringify(data));
        resolve(response);
      } catch (error) {
        reject(error);
      }
    }, 1e3);
  });
  const { name } = promise;
  console.log("用户姓名: ", name);
}
